﻿using System;
using System.Windows.Navigation;
using System.Windows.Data;
using System.Windows;
using System.ComponentModel;
using System.Windows.Interop;

using PasswordProvider.View.Library;
using PasswordProvider.View.Properties;
using System.Windows.Input;
using System.Reflection;

namespace PasswordProvider.View
{
    /// <summary>
    /// MainWindow: Application window. Inherits from NotificationWindow to provide the "run in notification area" feature.
    /// </summary>
    public sealed partial class MainWindow : NotificationWindow
    {
        #region Construction
        
        public MainWindow()
        {
            InitializeComponent();

            NotifyIcon.Icon = Properties.Resources.LockAndKey;
            NotifyIcon.Text = Title;

            _frameMain.Navigated +=
                 delegate
                 {
                     this.SetContextMenuEnabledStatus();
                 };

            Loaded += delegate
            {
                SetupNotificationIconContextMenu(DataContext);
            };
        }

       
        #endregion // Constructor.

        #region Properties

        /// <summary>
        /// Provides access to the frame's navigation service. 
        /// </summary>
        public NavigationService NavigationService
        {
            get { return _frameMain.NavigationService; }
        }

        #endregion

        #region Notify Icon Context menu

        // Sets up the context menu associated with the notification icon displayed 
        // in the notification area of the task bar. Note that it is a windows forms menu, not
        // a wpf menu, so 1) it can't be defined in xaml and 2) it doesn't support binding.
        private void SetupNotificationIconContextMenu(object viewModel)
        {
            if (viewModel == null)
                throw new ArgumentNullException("viewModel");

            // Trying to do this without actually referencing the viewModel libaray, for the fun of it.

            // Options
            object showOptionsCommand = GetPropertyValue("ShowOptionsCommand", viewModel);
            NotificationIconContextMenu.MenuItems.Add(
                (GetPropertyValue("DisplayName", showOptionsCommand) as string).Replace("_", ""),
                delegate
                {
                    ICommand command = GetPropertyValue("Command", showOptionsCommand) as ICommand;
                    if(command != null)
                        if (command.CanExecute(this))
                        {
                            command.Execute(this);
                            ShowWindow();
                        }
                });

            // Manage.
            object showManageCommand = GetPropertyValue("ShowManageCommand", viewModel);
            NotificationIconContextMenu.MenuItems.Add(
                (GetPropertyValue("DisplayName", showManageCommand) as string).Replace("_", ""),
                delegate
                {
                    ICommand command = GetPropertyValue("Command", showManageCommand) as ICommand;
                    if (command != null)
                        if (command.CanExecute(this))
                        {
                            command.Execute(this);
                            ShowWindow();
                        }
                });

            // Logout
            object logoutCommand = GetPropertyValue("LogOffCommand", viewModel);
            System.Windows.Forms.MenuItem logoutItem = NotificationIconContextMenu.MenuItems.Add(
                (GetPropertyValue("DisplayName", logoutCommand) as string).Replace("_", ""),
                delegate
                {
                    ICommand command = GetPropertyValue("Command", logoutCommand) as ICommand;
                    if (command != null)
                        if (command.CanExecute(this))                        
                            command.Execute(this);
                });
            logoutItem.Tag = "AlwaysEnabled";

            // Help
            object showHelpCommand = GetPropertyValue("ShowHelpCommand", viewModel);
            System.Windows.Forms.MenuItem helpItem = NotificationIconContextMenu.MenuItems.Add(
                (GetPropertyValue("DisplayName", showHelpCommand) as string).Replace("_", ""),
                delegate
                {
                    ICommand command = GetPropertyValue("Command", showHelpCommand) as ICommand;
                    if (command != null)
                        if (command.CanExecute(this))
                            command.Execute(this);
                });
            helpItem.Tag = "AlwaysEnabled";

            // Add Exit, include a tag on the menu item.
            System.Windows.Forms.MenuItem exitItem = NotificationIconContextMenu.MenuItems.Add("Exit",
                delegate
                {
                    Close();
                });
            exitItem.Tag = "AlwaysEnabled";

        }

        #endregion

        #region Private Methods

        // Use reflection to get the value of a named property on a target object.
        private static object GetPropertyValue(string propertyName, object targetObject)
        {
            Type vmType = targetObject.GetType();
            PropertyInfo prop = vmType.GetProperty(propertyName);
            if(prop == null)
                throw new ArgumentException(propertyName);

            return prop.GetValue(targetObject, null);            
        }
       
        // Setup the context menus, visibility and enabled status depending on 
        // current page and value of RunInSystemTray setting.
        private void SetContextMenuEnabledStatus()
        {
            bool enabled = _frameMain.Content.GetType().Name.ToString() == "SitesListViewModel";
            foreach (System.Windows.Forms.MenuItem item in NotificationIconContextMenu.MenuItems)
            {
                if ((string)item.Tag != "AlwaysEnabled") // exit and help are always enabled.
                    item.Enabled = enabled;
            }        
        }

        #endregion

    }
}
